var renderer,_program,_dt,_vao,_vao_ext;


function initShader() {
  const gl = renderer.getContext()
  const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM)
  const vs = `
        attribute vec2 a_position;
        attribute vec2 a_texCoord;
        uniform mat3 displayTransform;
        varying vec2 v_texCoord;
        void main() {
          vec3 p = displayTransform * vec3(a_position, 0);
          gl_Position = vec4(p.x, p.y, -1, 1);
          v_texCoord = a_texCoord;
        }
      `
  const fs = `
        precision highp float;

        uniform sampler2D y_texture;
        uniform sampler2D uv_texture;
        varying vec2 v_texCoord;
        void main() {
          vec4 y_color = texture2D(y_texture, v_texCoord);
          vec4 uv_color = texture2D(uv_texture, v_texCoord);

          float Y, U, V;
          float R ,G, B;
          Y = y_color.r;
          U = uv_color.r - 0.5;
          V = uv_color.a - 0.5;
          
          R = Y + 1.402 * V;
          G = Y - 0.344 * U - 0.714 * V;
          B = Y + 1.772 * U;
          
          gl_FragColor = vec4(R, G, B, 1.0);
        }
      `
  const vertShader = gl.createShader(gl.VERTEX_SHADER)
  gl.shaderSource(vertShader, vs)
  gl.compileShader(vertShader)

  const fragShader = gl.createShader(gl.FRAGMENT_SHADER)
  gl.shaderSource(fragShader, fs)
  gl.compileShader(fragShader)

  const program = _program = gl.createProgram()
  _program.gl = gl
  gl.attachShader(program, vertShader)
  gl.attachShader(program, fragShader)
  gl.deleteShader(vertShader)
  gl.deleteShader(fragShader)
  gl.linkProgram(program)
  gl.useProgram(program)

  const uniformYTexture = gl.getUniformLocation(program, 'y_texture')
  gl.uniform1i(uniformYTexture, 5)
  const uniformUVTexture = gl.getUniformLocation(program, 'uv_texture')
  gl.uniform1i(uniformUVTexture, 6)

  _dt = gl.getUniformLocation(program, 'displayTransform')
  gl.useProgram(currentProgram)
}

function initVAO() {
  const gl = renderer.getContext()
  const ext = gl.getExtension('OES_vertex_array_object')
  _vao_ext = ext

  const currentVAO = gl.getParameter(gl.VERTEX_ARRAY_BINDING)
  const vao = ext.createVertexArrayOES()

  ext.bindVertexArrayOES(vao)

  const posAttr = gl.getAttribLocation(_program, 'a_position')
  const pos = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, pos)
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW)
  gl.vertexAttribPointer(posAttr, 2, gl.FLOAT, false, 0, 0)
  gl.enableVertexAttribArray(posAttr)
  vao.posBuffer = pos

  const texcoordAttr = gl.getAttribLocation(_program, 'a_texCoord')
  const texcoord = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoord)
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, 0, 1, 1, 0, 0, 0]), gl.STATIC_DRAW)
  gl.vertexAttribPointer(texcoordAttr, 2, gl.FLOAT, false, 0, 0)
  gl.enableVertexAttribArray(texcoordAttr)
  vao.texcoordBuffer = texcoord

  ext.bindVertexArrayOES(currentVAO)
  _vao = vao
}

function initGL(_renderer) {
  console.log('initGL')
  renderer = _renderer
  initShader()
  initVAO()
}

function renderGL(frame) {
  const gl = renderer.getContext()
  // gl.disable(gl.DEPTH_TEST)
  const { yTexture, uvTexture } = frame.getCameraTexture(gl, 'yuv')
  const displayTransform = frame.getDisplayTransform()
  if (yTexture && uvTexture) {
    const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM)
    const currentActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE)
    const currentVAO = gl.getParameter(gl.VERTEX_ARRAY_BINDING)

    gl.useProgram(_program)
    _vao_ext.bindVertexArrayOES(_vao)

    gl.uniformMatrix3fv(_dt, false, displayTransform)
    gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1)

    gl.activeTexture(gl.TEXTURE0 + 5)
    const bindingTexture5 = gl.getParameter(gl.TEXTURE_BINDING_2D)
    gl.bindTexture(gl.TEXTURE_2D, yTexture)

    gl.activeTexture(gl.TEXTURE0 + 6)
    const bindingTexture6 = gl.getParameter(gl.TEXTURE_BINDING_2D)
    gl.bindTexture(gl.TEXTURE_2D, uvTexture)

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

    gl.bindTexture(gl.TEXTURE_2D, bindingTexture6)
    gl.activeTexture(gl.TEXTURE0 + 5)
    gl.bindTexture(gl.TEXTURE_2D, bindingTexture5)

    gl.useProgram(currentProgram)
    gl.activeTexture(currentActiveTexture)
    _vao_ext.bindVertexArrayOES(currentVAO)
  }
}

// 将对象回收
function dispose() {
  if (_program && _program.gl) {
    _program.gl.deleteProgram(_program)
    _program = null
  }
}


module.exports = {
  initGL,
  renderGL,
  dispose
}